package com.frontop.terminal.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.frontop.terminal.constant.CommonNumBerCodConst;
import com.frontop.terminal.constant.InterfaceConst;
import com.frontop.terminal.constant.PlayStatusConst;
import com.frontop.terminal.constant.ResourceTypeConst;
import com.frontop.terminal.downloader.MultipleThreadDownloadTask;
import com.frontop.terminal.entity.PlayList;
import com.frontop.terminal.entity.Program;
import com.frontop.terminal.entity.TerminalConfig;
import com.frontop.terminal.enums.HeaderEnum;
import com.frontop.terminal.model.bo.TerminalResourceBO;
import com.frontop.terminal.model.vo.LayUiResult;
import com.frontop.terminal.model.vo.ResourceVO;
import com.frontop.terminal.model.vo.RestResult;
import com.frontop.terminal.util.ReadDataUtil;
import com.frontop.terminal.util.SystemMonitoringUtil;
import com.frontop.terminal.util.WriteDataUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 资源导入
 * </P>
 *
 * @author :CCC
 * @since :2021-07-07 15:14:00
 **/
@SuppressWarnings("AlibabaUndefineMagicConstant")
@Controller
@RequestMapping("/terminal-resouce")
public class TerminalResouceController {

    @GetMapping("")
    public String index(HttpServletRequest request) {
        //用于前端在新增时判断是否显示主屏资源id输入框
        TerminalConfig terminalConfig = ReadDataUtil.getTerminalConfig();
        if (Objects.isNull(terminalConfig)) {
            terminalConfig = new TerminalConfig();
        }
        request.setAttribute("playerGanged", terminalConfig.isPlayerGanged());

        return "resouce";
    }

    @GetMapping("list")
    @ResponseBody
    public LayUiResult getList() {
        List<PlayList> playLists = ReadDataUtil.getPlayList();
        List<Program> programList = ReadDataUtil.getProgramList();
        List<ResourceVO> resourceVOList = new ArrayList<>(16);

        if (Objects.nonNull(playLists)) {
            for (PlayList p : playLists) {
                ResourceVO vo = BeanUtil.toBean(p, ResourceVO.class);
                resourceVOList.add(vo);
            }
        }
        if (Objects.nonNull(programList)) {
            for (Program p : programList) {
                ResourceVO vo = new ResourceVO();
                vo.setId(p.getId());
                vo.setName(p.getName());
                vo.setLocation(p.getLocation());
                vo.setGangedId(p.getGangedId());
                vo.setSource(p.getSource());
                vo.setType(CommonNumBerCodConst.TWO);
                resourceVOList.add(vo);
            }
        }

        return LayUiResult.success(null, resourceVOList.size(), resourceVOList);
    }

    @PutMapping("update")
    @ResponseBody
    public RestResult update(@RequestBody ResourceVO resourceVO) {
        System.out.println("修改资源,参数：" + resourceVO);
        boolean status = false;
        try {

            if (resourceVO.getType().equals(CommonNumBerCodConst.TWO)) {
                //-------------------------互动程序--------------------/
                List<Program> programList = ReadDataUtil.getProgramList();

                if (Objects.isNull(programList)) {
                    return RestResult.failed("源数据为空");
                }

                for (Program p : programList) {
                    if (p.getId().equals(resourceVO.getId())) {
                        p.setGangedId(resourceVO.getGangedId());
                        p.setLocation(resourceVO.getLocation());
                        //如果资源名称不同了同时通知中控服务修改名称
                        status = !p.getName().equals(resourceVO.getName());
                        p.setName(resourceVO.getName());

                        //保存
                        WriteDataUtil.write(programList, ReadDataUtil.PROGRAM_LIST_CODING);
                    }
                }

            } else {
                //-------------------------播放列表--------------------/
                List<PlayList> playListS = ReadDataUtil.getPlayList();

                if (Objects.isNull(playListS)) {
                    return RestResult.failed("源数据为空");
                }


                for (PlayList p : playListS) {
                    if (p.getId().equals(Long.parseLong(resourceVO.getId()))) {
                        //修改的路径不存在
                        if (!FileUtil.exist(resourceVO.getLocation())) {
                            return RestResult.failed("资源不存在，请检查资源路径是否正确");
                        }

                        p.setLocation(resourceVO.getLocation());
                        if (Objects.nonNull(resourceVO.getGangedId())) {
                            p.setGangedId(Long.parseLong(resourceVO.getGangedId()));
                        }

                        //如果资源名称不同了同时通知中控服务修改名称
                        status = !p.getName().equals(resourceVO.getName());
                        p.setName(resourceVO.getName());

                        //保存
                        WriteDataUtil.write(playListS, ReadDataUtil.PLAYLIST_LIST_CODING);
                    }
                }
            }

            //在修改了资源名称时进入
            if (status) {
                TerminalConfig terminalConfig = ReadDataUtil.getTerminalConfig();
                String url = Objects.requireNonNull(terminalConfig).getServerAddress() + InterfaceConst.UPDATE_RESOURCE_NAME;
                String mac = SystemMonitoringUtil.getMacAddress();

                TerminalResourceBO resourceBO = new TerminalResourceBO();
                resourceBO.setId(resourceVO.getId());
                resourceBO.setResourceName(resourceVO.getName());
                resourceBO.setMac(mac);

                HttpResponse httpResponse = HttpRequest.put(url)
                        //设置连接超时和响应超时时间
                        .timeout(10000)
                        .header(HeaderEnum.TERMINAL_TOKEN.getKey(), terminalConfig.getAuthorizationCode())
                        .body(JSON.toJSONString(resourceBO))
                        .contentType(ContentType.JSON.getValue())
                        .executeAsync();

                if (httpResponse.isOk()) {
                    if ("true".equals(httpResponse.body())) {
                        return RestResult.success();
                    }

                    return RestResult.failed("中控服务出现异常");
                } else {
                    return RestResult.failed("通知中控服务器同步修改资源名称失败");
                }
            }

            return RestResult.failed("系统异常，请稍后重试");

        } catch (Exception e) {
            e.printStackTrace();
            return RestResult.failed("系统异常，请稍后重试");
        }
    }

    @DeleteMapping("/{id}/{type}")
    @ResponseBody
    public RestResult del(@PathVariable String id, @PathVariable Integer type) {
        System.out.println("删除资源,id：" + id);
        try {
            //获取网址,进行通知服务器同步播放列表
            TerminalConfig terminalConfig = ReadDataUtil.getTerminalConfig();
            String url = Objects.requireNonNull(terminalConfig).getServerAddress() + InterfaceConst.DELETE_RESOURCE;
            String mac = SystemMonitoringUtil.getMacAddress();

            if (type.equals(CommonNumBerCodConst.TWO)) {
                //-------------------------互动程序--------------------/
                List<Program> programList = ReadDataUtil.getProgramList();

                if (Objects.isNull(programList)) {
                    return RestResult.failed("源数据为空");
                }

                for (Iterator<Program> it = programList.iterator(); it.hasNext(); ) {
                    if (it.next().getId().equals(id)) {
                        HttpResponse httpResponse = HttpRequest.delete(url)
                                //设置连接超时和响应超时时间
                                .timeout(3000)
                                .header(HeaderEnum.TERMINAL_TOKEN.getKey(), terminalConfig.getAuthorizationCode())
                                .form("mac", mac)
                                .form("id", id)
                                .form("type", type)
                                .executeAsync();

                        if (httpResponse.isOk()) {
                            //删除
                            it.remove();
                            //保存
                            WriteDataUtil.write(programList, ReadDataUtil.PROGRAM_LIST_CODING);
                            return RestResult.success();
                        }

                        System.out.println("通知中控服务器同步删除操作过程中出现异常");
                        return RestResult.failed("操作失败!原因：通知中控服务器同步删除操作过程中出现异常");
                    }
                }
            } else {
                //-------------------------播放列表--------------------/
                List<PlayList> playListS = ReadDataUtil.getPlayList();

                if (Objects.isNull(playListS)) {
                    return RestResult.failed("源数据为空");
                }


                for (Iterator<PlayList> it = playListS.iterator(); it.hasNext(); ) {
                    PlayList p = it.next();
                    if (p.getId().equals(Long.parseLong(id))) {
                        HttpResponse httpResponse = HttpRequest.delete(url)
                                //设置连接超时和响应超时时间
                                .timeout(3000)
                                .header(HeaderEnum.TERMINAL_TOKEN.getKey(), terminalConfig.getAuthorizationCode())
                                .form("mac", mac)
                                .form("id", id)
                                .form("type", type)
                                .executeAsync();

                        if (httpResponse.isOk()) {
                            //删除
                            it.remove();
                            //保存
                            WriteDataUtil.write(playListS, ReadDataUtil.PLAYLIST_LIST_CODING);
                            return RestResult.success();
                        }

                        System.out.println("通知中控服务器同步删除操作过程中出现异常");
                        return RestResult.failed("通知中控服务器同步删除操作过程中出现异常");

                    }
                }
            }

            return RestResult.success();
        } catch (IORuntimeException e) {
            System.out.println("中控服务离线,删除资源[" + id + "]失败");
            return RestResult.failed("中控服务离线,请稍后重试");
        } catch (Exception e) {
            e.printStackTrace();
            return RestResult.failed("系统异常，请稍后重试");
        }
    }

    @SuppressWarnings("ConstantConditions")
    @PostMapping("")
    @ResponseBody
    public RestResult add(@RequestParam String mediaName, @RequestParam Integer type, @RequestParam String resourceAddrs, Long gangedId) {
        boolean fileExist = FileUtil.exist(resourceAddrs);
        if (!fileExist) {
            return RestResult.failed("该资源不存在，请正确输入资源位置");
        }

        File file = new File(resourceAddrs);
        long fileSize = FileUtil.size(file);

        //获取网址,进行通知服务器同步播放列表
        TerminalConfig terminalConfig = ReadDataUtil.getTerminalConfig();
        String url = terminalConfig.getServerAddress() + InterfaceConst.ADD_RESOURCE;
        String mac = SystemMonitoringUtil.getMacAddress();

        try {
            //导入互动程序
            if (type.equals(ResourceTypeConst.INTERACTION)) {

                notificationSynchronizesLocalProgramList(mediaName, resourceAddrs, terminalConfig, url, mac, gangedId, type, fileSize);

            } else if (checkIsMedia(type)) {
                //检测资源名称是否已经存在
                List<PlayList> playLists = ReadDataUtil.getPlayList();
                if (playLists != null) {
                    for (PlayList p :
                            playLists) {
                        if (!StringUtils.isBlank(p.getName()) && p.getName().equals(mediaName)) {
                            return RestResult.failed("资源名称为[" + mediaName + "]已经存在");
                        }
                    }
                }

                //通知服务器同步本地播放列表（音频、图片、视频、待机）
                notificationSynchronizesLocalPlaylists(mediaName, type, resourceAddrs, fileSize, terminalConfig, url, mac, gangedId);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return RestResult.failed("导入失败，请稍后重试");
        }

        return RestResult.success();
    }

    private void notificationSynchronizesLocalProgramList(String mediaName, String resourceAddrs, TerminalConfig terminalConfig, String url, String mac, Long gangedId, Integer type, long fileSize) throws Exception {
        //读取本地互动程序
        List<Program> programList = ReadDataUtil.getProgramList();
        if (Objects.isNull(programList)) {
            programList = new ArrayList<>(1);
        }

        TerminalResourceBO resourceBO = new TerminalResourceBO();
        resourceBO.setResourceName(mediaName);
        resourceBO.setResourceType(ResourceTypeConst.converttoservercode(type));
        resourceBO.setMac(mac);
        resourceBO.setResourceSource(CommonNumBerCodConst.TWO);
        resourceBO.setSize(fileSize);
        resourceBO.setResourceLocation(resourceAddrs);

        HttpResponse httpResponse = HttpRequest.post(url)
                //设置连接超时和响应超时时间
                .timeout(10000)
                .header(HeaderEnum.TERMINAL_TOKEN.getKey(), terminalConfig.getAuthorizationCode())
                .body(JSON.toJSONString(resourceBO))
                .contentType(ContentType.JSON.getValue())
                .executeAsync();

        if (!httpResponse.isOk()) {
            throw new Exception("添加互动程序失败");
        }

        //服务器返回id
        String id = httpResponse.body().replaceAll("\"", "");
        System.out.println("[添加互动程序]接收到服务器回应:" + id);


        Program program = new Program(id, resourceAddrs, mediaName);
        program.setGangedId(String.valueOf(gangedId));
        programList.add(program);

        //http状态码200就将添加的程序信息保存本地记录
        WriteDataUtil.write(programList, ReadDataUtil.PROGRAM_LIST_CODING);

        //通知服务器更新资源发布状态
        MultipleThreadDownloadTask.updateMediaLinkState(Long.valueOf(id));
    }


    private void notificationSynchronizesLocalPlaylists(String mediaName, Integer type, String resourceAddrs, long fileSize, TerminalConfig terminalConfig, String url, String mac, Long gangedId) throws Exception {
        PlayList play = new PlayList();
        play.setLocation(resourceAddrs);
        play.setSource(1);
        play.setName(mediaName);
        play.setGangedId(gangedId);

        List<PlayList> playLists = ReadDataUtil.getPlayList();

        if (Objects.isNull(playLists)) {
            playLists = new ArrayList<>(1);
        }

        //如果待机资源

        //记录待机资源是否已经存在标志
        boolean standbyExist = false;
        if (type.equals(ResourceTypeConst.STANDBY)) {


            //遍历找出待机资源进行替换
            for (PlayList p :
                    playLists) {
                if (p.getType().equals(PlayStatusConst.TYPE_STANDBY_RESOURCE)) {
                    //更新
                    p.setLocation(resourceAddrs);
                    standbyExist = true;
                    break;
                }
            }

            play.setType(1);

        }

        //不存在则添加
        if (!standbyExist) {
            TerminalResourceBO resourceBO = new TerminalResourceBO();
            resourceBO.setResourceName(mediaName);
            resourceBO.setResourceType(ResourceTypeConst.converttoservercode(type));
            resourceBO.setSize(fileSize);
            resourceBO.setMac(mac);
            resourceBO.setResourceSource(CommonNumBerCodConst.TWO);
            resourceBO.setResourceLocation(resourceAddrs);

            HttpResponse httpResponse = HttpRequest.post(url)
                    //设置连接超时和响应超时时间
                    .timeout(10000)
                    .header(HeaderEnum.TERMINAL_TOKEN.getKey(), terminalConfig.getAuthorizationCode())
                    .body(JSON.toJSONString(resourceBO))
                    .contentType(ContentType.JSON.getValue())
                    .executeAsync();

            if (!httpResponse.isOk()) {
                throw new Exception("添加资源失败");
            }

            String body = httpResponse.body().replaceAll("\"", "");
            System.out.println("[添加资源]接收到服务器回应:" + body);

            //播放列表id
            long newMediaId = Long.parseLong(body);

            play.setId(newMediaId);
            playLists.add(play);

            //通知服务器更新资源发布状态
            MultipleThreadDownloadTask.updateMediaLinkState(newMediaId);
        }

        WriteDataUtil.write(playLists, ReadDataUtil.PLAYLIST_LIST_CODING);

    }

    private boolean checkIsMedia(Integer type) {
        return ResourceTypeConst.VIDEO.equals(type) || ResourceTypeConst.IMG.equals(type) || ResourceTypeConst.AUDIO.equals(type) || ResourceTypeConst.STANDBY.equals(type);
    }

}
